/***** Lobxxx Translate Finished ******/
/*
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

/*
 *
 *
 *
 *
 *
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the public domain, as explained at
 * http://creativecommons.org/publicdomain/zero/1.0/
 * <p>
 *  由Doug Lea在JCP JSR-166专家组成员的帮助下撰写,并发布到公共领域,如http://creativecommons.org/publicdomain/zero/1.0/
 * 
 */

package java.util.concurrent;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

/**
 *  允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助。
 * 
 *  <p>使用给定的<em>计数</em>初始化{@code CountDownLatch}。
 *  {@link #await await}方法阻塞,直到当前计数由于调用{@link #countDown}方法而达到零,之后所有等待的线程都被释放,并且任何后续的{@link #await await}
 * 调用立即返回。
 *  <p>使用给定的<em>计数</em>初始化{@code CountDownLatch}。这是一次性的现象 - 计数不能重置。
 * 如果您需要重置计数的版本,请考虑使用{@link CyclicBarrier}。
 * 
 *  <p> {@code CountDownLatch}是一种多功能同步工具,可用于多种用途。
 * 以计数为1初始化的{@code CountDownLatch}用作简单的开/关锁存器或门：所有调用{@link #await await}的线程在门处等待,直到它被调用{@link#倒数}。
 * 初始化为<em> N </em>的{@code CountDownLatch}可用于使一个线程等待,直到<em> N </em>个线程已完成某些操作,或某些操作已完成N次。
 * 
 * <p> {@code CountDownLatch}的一个有用的属性是它不需要调用{@code countDown}的线程等待计数达到零,然后继续,它只是阻止任何线程通过{@link #await await}
 * ,直到所有的线程都能通过。
 * 
 *  <p> <b>示例用法：</b>这是一对类,其中一组工作线程使用两个倒计时锁存：
 * <ul>
 *  <li>第一个是启动信号,防止任何工作人员继续进行,直到驱动程序准备好继续进行; <li>第二个是完成信号,允许驾驶员等待,直到所有工人完成。
 * </ul>
 * 
 *  <pre> {@code class Driver {// ... void main()throws InterruptedException {CountDownLatch startSignal = new CountDownLatch(1); CountDownLatch doneSignal = new CountDownLatch(N);。
 * 
 *  for(int i = 0; i <N; ++ i)//创建和启动线程new Thread(new Worker(startSignal,doneSignal))。
 * 
 *  doSomethingElse(); //不让运行startSignal.countDown(); //让所有线程继续doSomethingElse(); doneSignal.await(); //
 * 等待所有完成}}。
 * 
 *  类Worker实现Runnable {private final CountDownLatch startSignal; private final CountDownLatch doneSignal; Worker(CountDownLatch startSignal,CountDownLatch doneSignal){this.startSignal = startSignal; this.doneSignal = doneSignal; }
 *  public void run(){try {startSignal.await();做工作(); doneSignal.countDown(); } catch(InterruptedExcepti
 * on ex){} // return; }}。
 * 
 * void doWork(){...}}} </pre>
 * 
 *  <p>另一个典型的用法是将问题分成N个部分,用Runnable描述每个部分,执行该部分并对锁存器计数,并将所有Runnables排队到执行器。当所有子部分完成时,协调线程将能够通过等待。
 *  (当线程必须以这种方式重复倒计时,而不是使用{@link CyclicBarrier}。)。
 * 
 *  <pre> {@code class Driver2 {// ... void main()throws InterruptedException {CountDownLatch doneSignal = new CountDownLatch(N);执行器e = ...。
 * 
 *  for(int i = 0; i <N; ++ i)//创建和启动线程e.execute(new WorkerRunnable(doneSignal,i));
 * 
 *  doneSignal.await(); //等待所有完成}}
 *  <p>内存一致性影响：在计数达到零之前,在调用{@code countDown()} <a href="package-summary.html#MemoryVisibility"> <i>之前发生的
 * 线程中的操作</i > </a>在另一个线程中从相应的{@code await()}成功返回后的操作。
 * 
 * 
 * @since 1.5
 * @author Doug Lea
 */
public class CountDownLatch {
    /**
     *  同步控件CountDownLatch。使用AQS状态来表示计数。
     * 
     */
    private static final class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 4982264981922014374L;

        Sync(int count) {
            setState(count);
        }

        int getCount() {
            return getState();
        }

        protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }

        protected boolean tryReleaseShared(int releases) {
            // Decrement count; signal when transition to zero
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;
                int nextc = c-1;
                //CAS将计数器state的值减1
                if (compareAndSetState(c, nextc))
                    //当state为0时返回true
                    return nextc == 0;
            }
        }
    }

    private final Sync sync;

    /**
     * 构造一个用给定计数初始化的{@code CountDownLatch}。
     */
    public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

    /**
     *  导致当前线程等待,直到锁存器计数到零,除非线程{@linkplain线程#中断}。
     * 
     *  <p>如果当前计数为零,则此方法立即返回。
     * 
     *  <p>如果当前计数大于零,则当前线程变为禁用以用于线程调度目的,并处于休眠状态,直到发生以下两种情况之一：
     * <ul>
     *  <li>由于调用了{@link #countDown}方法,因此计数值为零;或<li>一些其他线程{@linkplain线程#中断中断}当前线程。
     * </ul>
     * 
     *  <p>如果当前线程：
     * <ul>
     *  <li>在进入此方法时设置了中断状态;或<li>是{@linkplain线程#中断}在等待时,
     * </ul>
     *  那么将抛出{@link InterruptedException},并清除当前线程的中断状态。
     */
    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

    /**
     *  导致当前线程等待,直到锁存器计数到零,除非线程{@linkplain线程#中断},或指定的等待时间过去。
     * 
     *  <p>如果当前计数为零,则此方法立即返回值{@code true}。
     * 
     *  <p>如果当前计数大于零,则当前线程因线程调度而被禁用,并处于休眠状态,直到发生以下三种情况之一：
     * <ul>
     * <li>由于调用了{@link #countDown}方法,因此计数值为零;或<li>一些其他线程{@linkplain线程#中断中断}当前线程;或<li>指定的等待时间已过。
     * </ul>
     * 
     *  <p>如果计数到达零,那么方法返回值为{@code true}。
     * 
     *  <p>如果当前线程：
     * <ul>
     *  <li>在进入此方法时设置了中断状态;或<li>是{@linkplain线程#中断}在等待时,
     * </ul>
     *  那么将抛出{@link InterruptedException},并清除当前线程的中断状态。
     */
    public boolean await(long timeout, TimeUnit unit)
        throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

    /**
     *  <p>如果经过指定的等待时间,则返回值{@code false}。如果时间小于或等于零,则该方法将不会等待。
     */
    public void countDown() {
        sync.releaseShared(1);
    }

    /**
     *  减少锁存器的计数,如果计数达到零,则释放所有等待的线程。
     * 
     *  <p>如果当前计数大于零,则递减。如果新计数为零,则为线程调度目的重新启用所有等待的线程。
     * 
     *  <p>如果当前计数等于零,那么什么也不发生。
     */
    public long getCount() {
        return sync.getCount();
    }

    /**
     * <p>
     *  返回当前计数。
     * 
     *  <p>此方法通常用于调试和测试目的。
     * 
     * 
     * @return a string identifying this latch, as well as its state
     */
    public String toString() {
        return super.toString() + "[Count = " + sync.getCount() + "]";
    }
}
